/*
 * Copyright 2012 The Netty Project
 *
 * The Netty Project licenses this file to you under the Apache License,
 * version 2.0 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at:
 *
 *   https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */
package com.king.netty.source.echo2;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.CharsetUtil;
import io.netty.util.concurrent.DefaultEventExecutorGroup;
import io.netty.util.concurrent.EventExecutorGroup;

import java.io.UnsupportedEncodingException;

/**
 * 任务在 handler 中加入异步线程
 */
@Sharable
public class EchoServerHandler extends ChannelInboundHandlerAdapter {

    /**
     * 业务线程池
     */
    static final EventExecutorGroup group = new DefaultEventExecutorGroup(16);

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println("EchoServerHandler 的线程是 = " + Thread.currentThread().getName());

        // 解法方案1 用户程序自定义的普通任务
//        ctx.channel().eventLoop().execute(new Runnable() {
//            @Override
//            public void run() {
//                try {
//                    Thread.sleep(5 * 1000);
//                    System.out.println("EchoServerHandler execute 线程是 = " + Thread.currentThread().getName());
//                    ctx.writeAndFlush(Unpooled.copiedBuffer("hello，客户端~", CharsetUtil.UTF_8));
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
//            }
//        });

        // 解决方案2 将任务提交到线程池
//        group.submit(new Callable<Object>() {
//            @Override
//            public Object call() throws Exception {
//                // 接收客户端消息
//                ByteBuf buf = (ByteBuf) msg;
//                byte[] bytes = new byte[buf.readableBytes()];
//                buf.readBytes(bytes);
//                String body = new String(bytes, "UTF-8");
//
//                // 模拟耗时任务
//                Thread.sleep(10 * 1000);
//
//                // 查看当前线程
//                System.out.println("EchoServerHandler group.submit 线程是 = " + Thread.currentThread().getName());
//
//                // 回复客户端
//                ctx.writeAndFlush(Unpooled.copiedBuffer("hello，客户端~", CharsetUtil.UTF_8));
//
//                return null;
//            }
//        });

        // 多个任务不会阻塞
//        group.submit(new Callable<Object>() {
//            @Override
//            public Object call() throws Exception {
//                // 接收客户端消息
//                ByteBuf buf = (ByteBuf) msg;
//                byte[] bytes = new byte[buf.readableBytes()];
//                buf.readBytes(bytes);
//                String body = new String(bytes, "UTF-8");
//
//                // 模拟耗时任务
//                Thread.sleep(10 * 1000);
//
//                // 查看当前线程
//                System.out.println("EchoServerHandler group.submit 线程是 = " + Thread.currentThread().getName());
//
//                // 回复客户端
//                ctx.writeAndFlush(Unpooled.copiedBuffer("hello，客户端~", CharsetUtil.UTF_8));
//
//                return null;
//            }
//        });

        // 普通方法，pipeline.addLast(group, EchoServerHandler)
        // 接收客户端消息
        ByteBuf buf = (ByteBuf) msg;
        byte[] bytes = new byte[buf.readableBytes()];
        buf.readBytes(bytes);
        String body = new String(bytes, "UTF-8");

        // 模拟耗时任务
        Thread.sleep(10 * 1000);

        // 查看当前线程
        System.out.println("EchoServerHandler group.submit 线程是 = " + Thread.currentThread().getName());

        // 回复客户端
        ctx.writeAndFlush(Unpooled.copiedBuffer("hello，客户端~", CharsetUtil.UTF_8));
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) {
        // 将数据写入缓存并刷新
        ctx.writeAndFlush(Unpooled.copiedBuffer("HELLO 客户端~", CharsetUtil.UTF_8));
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        ctx.close();
    }
}
